
use std::io::Write;

use super::bytes_io::BytesIO;



impl BytesIO {
    pub fn write_bytes(&mut self, buf: &[u8]) -> usize {
        let len_write = match self.write(buf) {
            Ok(v) => v,
            Err(e) => {
                let len_append = buf.len();
                let content = if len_append < 40 {
                    format!("({len_append} bytes){:?}", buf)
                } else {
                    format!("({len_append} bytes){:?} ...(more)", buf[0..20].to_vec())
                };
                error!("BytesIO::write error: {content}, {e:?}");
                return 0;
            },
        };
        len_write
    }
}

impl BytesIO {
    pub fn write_bool(&mut self, val: bool) -> usize {
        let src: [u8; 1] = [if val {1} else {0}];
        self.write_bytes(&src)
    }

    pub fn write_i8(&mut self, val: i8) -> usize {
        let src = [val as u8];
        self.write_bytes(&src)
    }
    pub fn write_u8(&mut self, val: u8) -> usize {
        let src = [val];
        self.write_bytes(&src)
    }
}

impl BytesIO {
    
    pub fn write_i16_le(&mut self, val: i16) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_i16_be(&mut self, val: i16) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
    
    pub fn write_u16_le(&mut self, val: u16) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_u16_be(&mut self, val: u16) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
}

impl BytesIO {
    pub fn write_i32_le(&mut self, val: i32) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_i32_be(&mut self, val: i32) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
    
    pub fn write_u32_le(&mut self, val: u32) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_u32_be(&mut self, val: u32) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }


    pub fn write_f32_le(&mut self, val: f32) -> usize {
        self.write_u32_le(val.to_bits())
    }

    pub fn write_f32_be(&mut self, val: f32) -> usize {
        self.write_u32_be(val.to_bits())
    }

}


impl BytesIO {
    pub fn write_i64_le(&mut self, val: i64) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_i64_be(&mut self, val: i64) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
    
    pub fn write_u64_le(&mut self, val: u64) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_u64_be(&mut self, val: u64) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
    
    pub fn write_f64_le(&mut self, val: f64) -> usize {
        self.write_u64_le(val.to_bits())
    }

    pub fn write_f64_be(&mut self, val: f64) -> usize {
        self.write_u64_be(val.to_bits())
    }
}

impl BytesIO {
    pub fn write_i128_le(&mut self, val: i128) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_i128_be(&mut self, val: i128) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
    
    pub fn write_u128_le(&mut self, val: u128) -> usize {
        self.write_bytes(&val.to_le_bytes())
    }
    pub fn write_u128_be(&mut self, val: u128) -> usize {
        self.write_bytes(&val.to_be_bytes())
    }
}

impl BytesIO {
    pub fn write_blob_without_size(&mut self, blob: &[u8]) -> usize {
        let len = blob.len();
        if len > i32::MAX as usize {
            panic!("BytesIO::write_blob_with_size, blob size must less than 2147483648, {len}");
        }
        self.write_bytes(blob);

        len
    }

    pub fn write_blob_with_size(&mut self, blob: &[u8]) -> usize {
        let len = blob.len();
        if len > i32::MAX as usize {
            panic!("BytesIO::write_blob_with_size, blob size must less than 2147483648, {len}");
        }
        
        let len_i32 = len as i32;
        self.write_i32_le(len_i32);
        self.write_bytes(blob);

        4 + len
    }
    pub fn write_utf8_with_size(&mut self, content: &str) -> usize {
        let blob = content.as_bytes();
        self.write_blob_with_size(blob)
    }
}